from django.core.management.base import BaseCommand
from django.utils import timezone
from django.db import transaction
from django.core.mail import send_mail
from django.conf import settings
from assets.models import Asset, InventoryAlert, AssetCategory, Department
from datetime import datetime, timedelta
import logging


class Command(BaseCommand):
    help = '智能库存预警生成器 - 基于资产状态和使用情况生成多维度预警'

    def __init__(self):
        super().__init__()
        self.logger = logging.getLogger(__name__)
        self.alert_stats = {
            'maintenance_overdue': 0,
            'warranty_expiring': 0,
            'idle_assets': 0,
            'high_value_unassigned': 0,
            'department_imbalance': 0,
            'category_shortage': 0,
            'total_processed': 0,
            'errors': 0
        }

    def add_arguments(self, parser):
        parser.add_argument(
            '--cleanup',
            action='store_true',
            help='清理已解决的旧预警记录',
        )
        parser.add_argument(
            '--days',
            type=int,
            default=30,
            help='清理多少天前的已解决预警（默认30天）',
        )
        parser.add_argument(
            '--send-email',
            action='store_true',
            help='发送预警邮件通知给管理员',
        )
        parser.add_argument(
            '--category',
            type=str,
            help='仅处理指定类别的资产预警',
        )
        parser.add_argument(
            '--department',
            type=str,
            help='仅处理指定部门的资产预警',
        )
        parser.add_argument(
            '--dry-run',
            action='store_true',
            help='预览模式，不实际创建预警记录',
        )
        parser.add_argument(
            '--verbose',
            action='store_true',
            help='显示详细的处理过程',
        )

    def handle(self, *args, **options):
        """主处理函数"""
        start_time = timezone.now()
        
        self._print_header()
        
        try:
            with transaction.atomic():
                # 生成各类预警
                self._generate_maintenance_alerts(options)
                self._generate_warranty_alerts(options)
                self._generate_idle_asset_alerts(options)
                self._generate_high_value_alerts(options)
                self._generate_department_alerts(options)
                self._generate_category_alerts(options)
                
                # 如果是预览模式，回滚事务
                if options['dry_run']:
                    transaction.set_rollback(True)
                    self.stdout.write(self.style.WARNING('🔍 预览模式：未实际创建预警记录'))
                
        except Exception as e:
            self.alert_stats['errors'] += 1
            self.stdout.write(self.style.ERROR(f'❌ 生成预警时发生错误：{str(e)}'))
            self.logger.error(f'Alert generation failed: {str(e)}', exc_info=True)
            return
        
        # 清理旧预警
        if options['cleanup']:
            self._cleanup_old_alerts(options)
        
        # 发送邮件通知
        if options['send_email'] and not options['dry_run']:
            self._send_email_notifications()
        
        # 显示统计结果
        self._print_summary(start_time)

    def _print_header(self):
        """打印命令头部信息"""
        self.stdout.write('\n' + '='*60)
        self.stdout.write(self.style.SUCCESS('🔔 智能库存预警生成器'))
        self.stdout.write('='*60)
        self.stdout.write(f'⏰ 开始时间: {timezone.now().strftime("%Y-%m-%d %H:%M:%S")}')
        self.stdout.write('')

    def _generate_maintenance_alerts(self, options):
        """生成维修超期预警"""
        if options['verbose']:
            self.stdout.write('🔧 检查维修超期资产...')
        
        # 查找维修中且超过30天的资产
        overdue_date = timezone.now() - timedelta(days=30)
        overdue_assets = Asset.objects.filter(
            status='maintenance',
            updated_at__lt=overdue_date
        )
        
        if options['category']:
            overdue_assets = overdue_assets.filter(category__name=options['category'])
        if options['department']:
            overdue_assets = overdue_assets.filter(department__name=options['department'])
        
        for asset in overdue_assets:
            if not options['dry_run']:
                InventoryAlert.objects.get_or_create(
                    asset=asset,
                    alert_type='maintenance_overdue',
                    defaults={
                        'message': f'资产 {asset.name} ({asset.asset_number}) 维修超期',
                        'priority': 'high',
                        'is_resolved': False
                    }
                )
            self.alert_stats['maintenance_overdue'] += 1
        
        if options['verbose']:
            self.stdout.write(f'  ✅ 发现 {self.alert_stats["maintenance_overdue"]} 个维修超期资产')

    def _generate_warranty_alerts(self, options):
        """生成保修到期预警"""
        if options['verbose']:
            self.stdout.write('📅 检查保修即将到期资产...')
        
        # 查找30天内保修到期的资产
        warning_date = timezone.now().date() + timedelta(days=30)
        expiring_assets = Asset.objects.filter(
            warranty_end_date__lte=warning_date,
            warranty_end_date__gte=timezone.now().date()
        )
        
        if options['category']:
            expiring_assets = expiring_assets.filter(category__name=options['category'])
        if options['department']:
            expiring_assets = expiring_assets.filter(department__name=options['department'])
        
        for asset in expiring_assets:
            if not options['dry_run']:
                InventoryAlert.objects.get_or_create(
                    asset=asset,
                    alert_type='warranty_expiring',
                    defaults={
                        'message': f'资产 {asset.name} ({asset.asset_number}) 保修即将到期',
                        'priority': 'medium',
                        'is_resolved': False
                    }
                )
            self.alert_stats['warranty_expiring'] += 1
        
        if options['verbose']:
            self.stdout.write(f'  ✅ 发现 {self.alert_stats["warranty_expiring"]} 个保修即将到期资产')

    def _generate_idle_asset_alerts(self, options):
        """生成闲置资产预警"""
        if options['verbose']:
            self.stdout.write('💤 检查长期闲置资产...')
        
        # 查找闲置超过60天的资产
        idle_date = timezone.now() - timedelta(days=60)
        idle_assets = Asset.objects.filter(
            status='idle',
            updated_at__lt=idle_date
        )
        
        if options['category']:
            idle_assets = idle_assets.filter(category__name=options['category'])
        if options['department']:
            idle_assets = idle_assets.filter(department__name=options['department'])
        
        for asset in idle_assets:
            if not options['dry_run']:
                InventoryAlert.objects.get_or_create(
                    asset=asset,
                    alert_type='idle_asset',
                    defaults={
                        'message': f'资产 {asset.name} ({asset.asset_number}) 长期闲置',
                        'priority': 'low',
                        'is_resolved': False
                    }
                )
            self.alert_stats['idle_assets'] += 1
        
        if options['verbose']:
            self.stdout.write(f'  ✅ 发现 {self.alert_stats["idle_assets"]} 个长期闲置资产')

    def _generate_high_value_alerts(self, options):
        """生成高价值未分配资产预警"""
        if options['verbose']:
            self.stdout.write('💰 检查高价值未分配资产...')
        
        # 查找价值超过10000且未分配用户的资产
        high_value_assets = Asset.objects.filter(
            purchase_price__gt=10000,
            user__isnull=True,
            status='idle'
        )
        
        if options['category']:
            high_value_assets = high_value_assets.filter(category__name=options['category'])
        if options['department']:
            high_value_assets = high_value_assets.filter(department__name=options['department'])
        
        for asset in high_value_assets:
            if not options['dry_run']:
                InventoryAlert.objects.get_or_create(
                    asset=asset,
                    alert_type='high_value_unassigned',
                    defaults={
                        'message': f'高价值资产 {asset.name} ({asset.asset_number}) 未分配使用人',
                        'priority': 'high',
                        'is_resolved': False
                    }
                )
            self.alert_stats['high_value_unassigned'] += 1
        
        if options['verbose']:
            self.stdout.write(f'  ✅ 发现 {self.alert_stats["high_value_unassigned"]} 个高价值未分配资产')

    def _generate_department_alerts(self, options):
        """生成部门资产分配不均预警"""
        if options['verbose']:
            self.stdout.write('🏢 检查部门资产分配情况...')
        
        # 简化的部门不均衡检查
        departments = Department.objects.all()
        avg_assets_per_dept = Asset.objects.count() / max(departments.count(), 1)
        
        for dept in departments:
            dept_asset_count = Asset.objects.filter(department=dept).count()
            if dept_asset_count > avg_assets_per_dept * 2:  # 超过平均值2倍
                if not options['dry_run']:
                    InventoryAlert.objects.get_or_create(
                        department=dept,
                        alert_type='department_imbalance',
                        defaults={
                            'message': f'部门 {dept.name} 资产配置过多 ({dept_asset_count} 个)',
                            'priority': 'medium',
                            'is_resolved': False
                        }
                    )
                self.alert_stats['department_imbalance'] += 1
        
        if options['verbose']:
            self.stdout.write(f'  ✅ 发现 {self.alert_stats["department_imbalance"]} 个部门分配不均情况')

    def _generate_category_alerts(self, options):
        """生成类别资产短缺预警"""
        if options['verbose']:
            self.stdout.write('📊 检查资产类别短缺情况...')
        
        # 检查每个类别的可用资产数量
        categories = AssetCategory.objects.all()
        
        for category in categories:
            available_count = Asset.objects.filter(
                category=category,
                status='idle'
            ).count()
            
            # 如果可用资产少于2个，生成预警
            if available_count < 2:
                if not options['dry_run']:
                    InventoryAlert.objects.get_or_create(
                        category=category,
                        alert_type='category_shortage',
                        defaults={
                            'message': f'资产类别 {category.name} 可用数量不足 ({available_count} 个)',
                            'priority': 'medium',
                            'is_resolved': False
                        }
                    )
                self.alert_stats['category_shortage'] += 1
        
        if options['verbose']:
            self.stdout.write(f'  ✅ 发现 {self.alert_stats["category_shortage"]} 个类别短缺情况')

    def _cleanup_old_alerts(self, options):
        """清理旧的已解决预警"""
        self.stdout.write('🧹 清理旧预警记录...')
        
        try:
            days = options['days']
            cutoff_date = timezone.now() - timedelta(days=days)
            
            deleted_count, _ = InventoryAlert.objects.filter(
                is_resolved=True,
                resolved_at__lt=cutoff_date
            ).delete()
            
            self.stdout.write(
                self.style.SUCCESS(f'  ✅ 清理了 {deleted_count} 个 {days} 天前的已解决预警')
            )
            
        except Exception as e:
            self.stdout.write(
                self.style.ERROR(f'  ❌ 清理预警失败：{str(e)}')
            )

    def _send_email_notifications(self):
        """发送邮件通知"""
        if not hasattr(settings, 'EMAIL_HOST') or not settings.EMAIL_HOST:
            self.stdout.write(self.style.WARNING('📧 邮件配置未设置，跳过邮件通知'))
            return
        
        try:
            total_alerts = sum([
                self.alert_stats['maintenance_overdue'],
                self.alert_stats['warranty_expiring'],
                self.alert_stats['high_value_unassigned']
            ])
            
            if total_alerts > 0:
                subject = f'资产管理系统预警通知 - {total_alerts} 个重要预警'
                message = self._build_email_message()
                
                send_mail(
                    subject=subject,
                    message=message,
                    from_email=settings.DEFAULT_FROM_EMAIL,
                    recipient_list=[settings.ADMIN_EMAIL],
                    fail_silently=False,
                )
                
                self.stdout.write(self.style.SUCCESS('📧 邮件通知发送成功'))
            
        except Exception as e:
            self.stdout.write(self.style.ERROR(f'📧 邮件发送失败：{str(e)}'))

    def _build_email_message(self):
        """构建邮件内容"""
        message = f"""资产管理系统预警报告
生成时间：{timezone.now().strftime('%Y-%m-%d %H:%M:%S')}

预警统计：
- 维修超期：{self.alert_stats['maintenance_overdue']} 个
- 保修到期：{self.alert_stats['warranty_expiring']} 个
- 长期闲置：{self.alert_stats['idle_assets']} 个
- 高价值未分配：{self.alert_stats['high_value_unassigned']} 个
- 部门分配不均：{self.alert_stats['department_imbalance']} 个
- 类别短缺：{self.alert_stats['category_shortage']} 个

请及时登录系统查看详细信息并处理相关预警。

此邮件由系统自动发送，请勿回复。
"""
        return message

    def _print_summary(self, start_time):
        """打印执行摘要"""
        end_time = timezone.now()
        duration = (end_time - start_time).total_seconds()
        
        total_alerts = sum([
            self.alert_stats['maintenance_overdue'],
            self.alert_stats['warranty_expiring'],
            self.alert_stats['idle_assets'],
            self.alert_stats['high_value_unassigned'],
            self.alert_stats['department_imbalance'],
            self.alert_stats['category_shortage']
        ])
        
        self.stdout.write('\n' + '='*60)
        self.stdout.write(self.style.SUCCESS('📊 执行摘要'))
        self.stdout.write('='*60)
        
        # 预警统计
        self.stdout.write('🔔 预警统计：')
        self.stdout.write(f'  • 维修超期：{self.alert_stats["maintenance_overdue"]} 个')
        self.stdout.write(f'  • 保修到期：{self.alert_stats["warranty_expiring"]} 个')
        self.stdout.write(f'  • 长期闲置：{self.alert_stats["idle_assets"]} 个')
        self.stdout.write(f'  • 高价值未分配：{self.alert_stats["high_value_unassigned"]} 个')
        self.stdout.write(f'  • 部门分配不均：{self.alert_stats["department_imbalance"]} 个')
        self.stdout.write(f'  • 类别短缺：{self.alert_stats["category_shortage"]} 个')
        self.stdout.write('')
        
        # 总计
        self.stdout.write(self.style.SUCCESS(f'✅ 总计生成预警：{total_alerts} 个'))
        self.stdout.write(f'⏱️  执行时间：{duration:.2f} 秒')
        self.stdout.write(f'🏁 完成时间：{end_time.strftime("%Y-%m-%d %H:%M:%S")}')
        
        if self.alert_stats['errors'] > 0:
            self.stdout.write(self.style.ERROR(f'❌ 错误数量：{self.alert_stats["errors"]} 个'))
        
        self.stdout.write('\n' + self.style.SUCCESS('🎉 库存预警生成完成！'))
        self.stdout.write('='*60 + '\n')
